package com.bw.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.ORDER;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;

public class SolrUtil {
	private HttpSolrClient client = null;
	private String url = "http://localhost:8984/solr/new_core5";
	
	public SolrUtil()
	{
		client = new HttpSolrClient(url);
	}
	
	/**
	 * 通过Map数据结构向Solr添加数据
	 * @param m
	 */
	public void addMap(Map<String,Object> m)
	{
		try
		{
			SolrInputDocument doc = new SolrInputDocument();
			for(String key:m.keySet())
			{
				Object obj = m.get(key);
				doc.addField(key, obj);
			}
			client.add(doc);
			UpdateResponse res = client.commit();
			System.out.println(res);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 通过ID删除Solr中的数据
	 * @param id
	 */
	public void deleteDocById(String id)
	{
		try
		{
			client.deleteById(id);
			UpdateResponse res = client.commit();
			System.out.println(res);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 通过查询删除Solr中的数据
	 * @param query 查询条件如 name:value 或 name:value AND desc:value
	 */
	public void deleteDocByQuery(String query)
	{
		try
		{
			client.deleteByQuery(query);
			UpdateResponse res = client.commit();
			System.out.println(res);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 通过Map更新Solr中对应的数据,Map中必须id键
	 * @param m
	 */
	public void updateMap(Map<String,Object> m)
	{
		try
		{
			if(!m.containsKey("id"))
			{
				throw new Exception("方法updateMap的参数必须包含Key id");
			}
			SolrInputDocument doc = new SolrInputDocument();
			Object id = m.get("id");
			doc.addField("id", id);
			for(String key:m.keySet())
			{
				if(!"id".equals(key))
				{
					Object obj = m.get(key);
					Map fmap = new HashMap();
					fmap.put("set", obj);
					doc.addField(key, fmap);
				}
			}
			client.add(doc);
			UpdateResponse resp = client.commit();
			System.out.println(resp);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 
	 * @param clz 用户定义类对应Class
	 * @param query 查询条件，例如name:iphone,name:iphone AND price:[2000 TO *]
	 * @param starts 开始记录数
	 * @param rows 每页显示记录数
	 * @param isHl 是否高亮显示关键字
	 * @param hlFlds 高亮显示字段的集合
	 * @param sortFld 排序的字段
	 * @param order asc/desc
	 * @return
	 */
	public <T> ResultInfo<T> queryBeans(Class clz,String query,Integer starts,
			Integer rows,boolean isHl,List<String> hlFlds,
			String sortFld,String order)
	{
		ResultInfo<T> result = new ResultInfo<T>();
		List<T> rtns = new ArrayList<T>();
		try
		{
			SolrQuery sq = new SolrQuery();
			sq.set("q", query);
			sq.set("fl", "*");
			sq.setHighlight(isHl);
			if(sortFld != null && !"".equals(sortFld))
			{
				System.out.println("----进入排序----");
				if("asc".equals(order))
					sq.addSort(sortFld, ORDER.asc);
				else
					sq.addSort(sortFld, ORDER.desc);
			}
			if(hlFlds != null)
			{
				sq.setHighlightSimplePre("<font color='red'>");
				sq.setHighlightSimplePost("</font>");
				StringBuffer sb = new StringBuffer();
				for(String str:hlFlds)
				{
					sb.append(str);
					sb.append(",");
				}
				String str = sb.toString();
				if(str.endsWith(","))
					str = str.substring(0,str.length()-1);
				sq.set("hl.fl", str);
			}
			
			sq.setStart(starts);
			sq.setRows(rows);
			QueryResponse resp = client.query(sq);
			Long total = resp.getResults().getNumFound();
			result.setTotal(total);
			Map<String,Map<String,List<String>>> hlMap = resp.getHighlighting();
			SolrDocumentList list = resp.getResults();
			Iterator<SolrDocument> it = list.iterator();
			for(;it.hasNext();)
			{
				SolrDocument doc = it.next();
				String fid = (String)doc.getFieldValue("id");
				Map<String,List<String>> hlMap2 = new HashMap<String,List<String>>();
				if(hlMap != null)
					hlMap2 = hlMap.get(fid);
				Field[] fdim = clz.getDeclaredFields();
				T infoObj = (T)clz.newInstance();
				for(Field f:fdim)
				{
					String fName = f.getName();
					List<String> hlList3 = hlMap2.get(fName);
					Object fObj = doc.getFieldValue(fName);
					String sVal = processMultiValue(fObj);
					//替换高亮显示数据域的值，添加高亮显示标识
					if(hlFlds != null && hlFlds.contains(fName))
					{
						if(hlList3 != null && hlList3.size()>0)
						{
							String hlStr = hlList3.get(0);
							sVal = processMultiValue(hlStr);
							System.out.println(fName+",value="+sVal);
						}
					}
					if(f.getType() == Integer.class)
					{
						try
						{
							BeanUtils.setProperty(infoObj, fName, new Integer(sVal));
						}
						catch(Exception e){}
					}
					if(f.getType() == Float.class)
					{
						try
						{
							BeanUtils.setProperty(infoObj, fName, new Float(sVal));
						}
						catch(Exception e){}
					}
					if(f.getType() == java.sql.Date.class)
					{
						try
						{
							java.util.Date dt = new java.util.Date(sVal);
							java.sql.Date dt2 = new java.sql.Date(dt.getTime());
							BeanUtils.setProperty(infoObj, fName, dt2);
						}
						catch(Exception e){}
					}
					if(f.getType() == String.class)
					{
						BeanUtils.setProperty(infoObj, fName, sVal);
					}

				}
				rtns.add((T)infoObj);
			}
			result.setList(rtns);
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 处理Solr返回多值方法
	 * @param obj
	 * @return
	 */
	private String processMultiValue(Object obj)
	{
		if(obj == null)
			return "";
		String str = obj.toString();
		if(str.startsWith("[") && str.endsWith("]"))
		{
			str = str.substring(1, str.length()-1);
			return str;
		}
		return obj.toString();
	}
	
	private void fillObjectProp(Class clz,String methodName,
			Object infoObj,Object fldVal) throws Exception
	{
		Method[] mdim = clz.getDeclaredMethods();
		for(Method m:mdim)
		{
			if(m.getName().equalsIgnoreCase(methodName))
			{
				m.invoke(infoObj,new Object[]{fldVal});
			}
		}
	}
	
}
